package com.assistant.util;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.config.ConnectionConfig;
import org.apache.http.config.MessageConstraints;
import org.apache.http.config.SocketConfig;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author xiong on 2018/12/21.
 */
@Slf4j
public class HttpClientUtils {
    private final static PoolingHttpClientConnectionManager httpClientManager = new PoolingHttpClientConnectionManager();
    private final static CloseableHttpClient httpClient;
    private static final  int SUCCESS = 200;
    static {
        MessageConstraints messageConstraints = MessageConstraints.custom().setMaxHeaderCount(200)
                .setMaxLineLength(2000).build();
        ConnectionConfig connectionConfig = ConnectionConfig.custom().setCharset(Consts.UTF_8)
                .setMessageConstraints(messageConstraints).build();
        httpClientManager.setDefaultConnectionConfig(connectionConfig);

        SocketConfig socketConfig = SocketConfig.custom().setTcpNoDelay(true).setSoKeepAlive(true).setSoTimeout(5000)
                .setSoReuseAddress(true).build();
        httpClientManager.setDefaultSocketConfig(socketConfig);

        httpClientManager.setMaxTotal(200);
        httpClientManager.setDefaultMaxPerRoute(60);
        httpClient = HttpClients.custom().disableRedirectHandling().setConnectionManager(httpClientManager).build();
    }

    public static CloseableHttpClient getHttpClient() {
        return httpClient;
    }

    public static String post(String url, Map<String, String> postData) {
        HttpPost httpPost = new HttpPost(url);
        HttpContext context = HttpClientContext.create();

        List<BasicNameValuePair> params = new ArrayList();
        if (postData != null) {
            for (String key : postData.keySet()) {
                params.add(new BasicNameValuePair(key, postData.get(key)));
            }
        }

        HttpEntity httpentity = new UrlEncodedFormEntity(params, Consts.UTF_8);
        httpPost.setEntity(httpentity);

        return execute(httpPost, context);
    }

    public static String postJson(String url, Object params) {
        HttpPost httpPost = new HttpPost(url);
        StringEntity requestEntity = new StringEntity(JSON.toJSONString(params), "utf-8");
        requestEntity.setContentEncoding("UTF-8");
        httpPost.setHeader("Content-type", "application/json");
        httpPost.setEntity(requestEntity);

        HttpContext context = HttpClientContext.create();
        return execute(httpPost, context);
    }

    public static String get(String url, Map<String, String> header) {
        HttpGet httpGet = new HttpGet(url);
        if (header != null) {
            for (String key : header.keySet()) {
                httpGet.addHeader(key, header.get(key));
            }
        }
        HttpContext context = HttpClientContext.create();

        return execute(httpGet, context);
    }

    private static String execute(HttpUriRequest request, HttpContext context) {
        CloseableHttpResponse response = null;
        CloseableHttpClient httpClient = getHttpClient();
        try {

            response = httpClient.execute(request, context);
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != SUCCESS) {
                log.error("statusCode:" + statusCode + ". url:" + request.getURI());
            } else {
                return EntityUtils.toString(response.getEntity(), Consts.UTF_8);
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            log.error("error:" + ex.getMessage(), ex);
        } finally {
            if (response != null) {
                try {
                    response.close();
                } catch (Exception e) {
                    e.printStackTrace();
                    log.error("error:" + e.getMessage(), e);
                }
            }
        }
        return null;
    }
}
